		TITLE	COMDEF - Copyright (c) SLR Systems 1994

		INCLUDE	MACROS
		INCLUDE	SYMBOLS
		INCLUDE	SEGMENTS
		INCLUDE	CDDATA

		PUBLIC	COMDEF,LCOMDF


		.DATA

		EXTERNDEF	COMM_TYPE:BYTE,COMM_NUMBER:BYTE,MCD_FLAGS:BYTE,COMDAT_FLAGS:BYTE,COMDAT_ALIGN:BYTE
		EXTERNDEF	COMDAT_ATTRIB:BYTE

		EXTERNDEF	SYM_HASH_MOD:DWORD,END_OF_RECORD:DWORD,CURNMOD_GINDEX:DWORD,TYPDEF_ANDER:DWORD,CURN_LIB_MODULE:DWORD
		EXTERNDEF	CV_TYPE:DWORD,CURNLIB_GINDEX:DWORD,COMDAT_GINDEX:DWORD,COMDAT_GROUP_LINDEX:DWORD
		EXTERNDEF	COMDAT_SEGMOD_LINDEX:DWORD,MYCOMDAT_LINDEX:DWORD,LAST_EXTDEF_GINDEX:DWORD,COMM_SIZE_A:DWORD
		EXTERNDEF	COMM_SIZE_B:DWORD

		EXTERNDEF	SYMBOL_LARRAY:LARRAY_STRUCT,SEGMOD_GARRAY:STD_PTR_S,SYMBOL_GARRAY:STD_PTR_S,SYMBOL_TPTR:TPTR_STRUCT

		EXTERNDEF	OPTI_MOVE:DWORD


		.CODE	PASS1_TEXT

		EXTERNDEF	REMOVE_FROM_EXTERNAL_LIST:PROC,OBJ_PHASE:PROC,_err_abort:proc,GET_32:PROC,FAR_INSTALL:PROC
		EXTERNDEF	DO_DEFINE_MODULE:PROC,REMOVE_FROM_WEAK_LIST:PROC,PREV_DEF_FAIL:PROC,REMOVE_FROM_LIBSYM_LIST:PROC
		EXTERNDEF	REMOVE_FROM_ALIASED_LIST:PROC,STORE_XREF_ENTRY:PROC,MYCOMDAT_INSTALL:PROC
		EXTERNDEF	REMOVE_FROM_WEAK_DEFINED_LIST:PROC,REMOVE_FROM_LAZY_DEFINED_LIST:PROC,ADD_TO_COMMUNAL_LIST:PROC
		EXTERNDEF	REMOVE_FROM_ALIAS_DEFINED_LIST:PROC,REMOVE_FROM_LAZY_LIST:PROC,ADD_TO_VIRDEF_LIST:PROC
		EXTERNDEF	FLUSH_COMDAT:PROC,HANDLE_COMDAT:PROC,REMOVE_FROM__IMP__LIST:PROC

		EXTERNDEF	MIC_NUM_ERR:ABS


LCOMDF		PROC

		MOV	EAX,CURNMOD_GINDEX

		OR	EAX,EAX
		JZ	L5$

		MOV	SYM_HASH_MOD,EAX
		CALL	COMDEF_TOP

		XOR	EAX,EAX

		MOV	SYM_HASH_MOD,EAX

		RET

L5$:
		CALL	DO_DEFINE_MODULE
		JMP	LCOMDF

LCOMDF		ENDP


COMDEF		PROC
		;
		;
		;
		MOV	EAX,CURNMOD_GINDEX

		TEST	EAX,EAX
		JNZ	COMDEF_TOP

		CALL	DO_DEFINE_MODULE

		JMP	COMDEF_TOP

OOPS:
		CALL	OBJ_PHASE
		RET

COMDEF_END:
		JNZ	OOPS
		RET

DONE_COMM:
		POP	ESI

COMDEF_TOP	LABEL	PROC

		CMP	END_OF_RECORD,ESI
		JBE	COMDEF_END

		MOV	EDI,OFF SYMBOL_TPTR
		ASSUME	EDI:PTR TPTR_STRUCT
		GET_NAME_HASH		;GET SYMBOL NAME - HASH IN EDX

		NEXT_INDEXI	

		AND	EAX,TYPDEF_ANDER	;0 IF NO CV TYPES THIS MODULE
		MOV	CL,[ESI]

		MOV	CV_TYPE,EAX	;PUT CV_INDEX
		INC	ESI

		MOV	COMM_NUMBER,CL
		CALL	NEXT_MIC_NUMBER	;EAX

		CMP	CL,61H			;61H IS A FAR COMMUNAL, 62H IS NEAR, BELOW IS A VIRDEF
		MOV	COMM_SIZE_A,EAX		;ASSUME	NEAR

		MOV	EAX,1
		MOV	BL,NSYM_NCOMM_UNREF

		JNZ	NOW_DEFINE_IT

		CALL	NEXT_MIC_NUMBER		;EAX	;FAR, GET ANOTHER NUMBER

		MOV	BL,NSYM_FCOMM_UNREF
NOW_DEFINE_IT:
		MOV	COMM_SIZE_B,EAX
		MOV	COMM_TYPE,BL

		PUSH	ESI
		CALL	FAR_INSTALL	;EAX IS GINDEX, ECX IS PHYS
		ASSUME	ECX:PTR SYMBOL_STRUCT

		MOV	EDX,EAX
if	fg_td
		MOV	LAST_EXTDEF_GINDEX,EAX	;FOR BORLAND INFO
endif
		INSTALL_GINDEX_LINDEX	SYMBOL_LARRAY

		MOV	EAX,EDX
		MOV	EBX,ECX
		ASSUME	EBX:PTR SYMBOL_STRUCT

		MOV	DL,[ECX]._S_REF_FLAGS
		GETT	CL,XREF_OUT

		TEST	CL,CL
		JZ	L3$

		AND	DL,MASK S_SPACES		;DON'T XREF LOCAL SYMBOLS...
		JNZ	L3$

		MOV	ECX,EBX
		CALL	STORE_XREF_ENTRY
L3$:
		MOV	ESI,DPTR [EBX]._S_NSYM_TYPE
		MOV	ECX,EBX

		MOV	DL,COMM_NUMBER
		MOV	BL,[EBX]._S_REF_FLAGS

		AND	ESI,NSYM_ANDER
		OR	BL,MASK S_SOFT_REF + MASK S_DATA_REF		;FORCE SOFT-REFERENCE ON COMMUNALS AND BVIRDEFS

		CMP	DL,61H
		JB	L2$

		MOV	[ECX]._S_REF_FLAGS,BL				;FORCE DATA-REFERENCE ON COMMUNALS

		CALL	COMDEF_TABLE[ESI*2]

		JMP	DONE_COMM

L2$:
		AND	BL,NOT MASK S_DATA_REF

		MOV	[ECX]._S_REF_FLAGS,BL
		CALL	PROCESS_VIRDEF

		JMP	DONE_COMM

COMDEF		ENDP


COMPARE_SIZES	PROC	NEAR
		;
		;DIFFERENT, WHICH IS LARGER?
		;
		MOV	EAX,COMM_SIZE_A
		MOV	EBX,[ECX]._COMM_SIZE_A

		CMP	EBX,EAX
		JNZ	L5$

		MOV	EAX,COMM_SIZE_B
		MOV	EBX,[ECX]._COMM_SIZE_B

		CMP	EBX,EAX
		JNZ	L5$

		RET

L5$:
		MOV	EAX,[ECX]._COMM_SIZE_A

		MUL	[ECX]._COMM_SIZE_B

		MOV	EBX,EAX
		MOV	EAX,COMM_SIZE_A

		MUL	COMM_SIZE_B

		CMP	EAX,EBX

		RET

COMPARE_SIZES	ENDP


ME_DONE_COMM	PROC	NEAR
		;
		;IN REFERENCED LIBRARY-LIST
		;IF THIS MODULE, MAKE COMMUNAL, ELSE IGNORE
		;
		GETT	DL,COMDEF_SEARCH
		MOV	EBX,CURN_LIB_MODULE

		TEST	DL,DL
		JZ	L5$

		MOV	EDX,[ECX]._S_LIB_MODULE
		MOV	ESI,CURNLIB_GINDEX

		CMP	EDX,EBX
		JNZ	L9$

		CMP	[ECX]._S_LIB_GINDEX,ESI
		JNZ	L9$
L5$:
		CALL	REMOVE_FROM_LIBSYM_LIST	;ONLY HAPPENS WITH BUSTED LIBRARIANS
		JMP	CMC_1

L9$:
		RET

ME_DONE_COMM	ENDP


PREV_COMDAT	PROC	NEAR
		;
		;IS IT CODE? IF DO, ERROR, ELSE OK
		;
		MOV	EAX,[ECX]._S_CD_SEGMOD_GINDEX
		CONVERT	EAX,EAX,SEGMOD_GARRAY

		MOV	AL,[EAX].SEGMOD_STRUCT._SM_FLAGS

		TEST	AL,MASK SEG_CLASS_IS_CODE
		JNZ	PREV_DEF_1

		RET

PREV_COMDAT	ENDP


PREV_RELOC	PROC	NEAR
		;
		;IS IT CODE? IF SO, ERROR, ELSE OK
		;
		MOV	EAX,[ECX]._S_SEG_GINDEX	;SEGMOD
		CONVERT	EAX,EAX,SEGMOD_GARRAY

		MOV	AL,[EAX].SEGMOD_STRUCT._SM_FLAGS

		TEST	AL,MASK SEG_CLASS_IS_CODE
		JZ	L9$
PREV_DEF_1::
		CALL	PREV_DEF_FAIL
L9$:
		RET

PREV_RELOC	ENDP

PREV_COMM_UNREF_HUGE::
PREV_COMMUNAL_HUGE	PROC	NEAR
		;
		;already communal, near overrides far, and use largest size
		;
		RET

PREV_COMMUNAL_HUGE	ENDP


PREV_COMM_UNREF	PROC	NEAR
		;
		;
		;
		MOV	AL,NSYM_NCOMM_UNREF
		JMP	PC_1

PREV_COMM_UNREF	ENDP


PREV_COMMUNAL	PROC	NEAR
		;
		;already communal, near overrides far, and use largest size
		;
		MOV	AL,NSYM_COMM_NEAR
PC_1::
		MOV	BL,COMM_NUMBER

		CMP	BL,62H			;IS THIS ONE NEAR?
		JZ	PC_2			;YES, FORCE NEAR
		MOV	AL,[ECX]._COMM_NSYM_TYPE	;ELSE, USE TYPE OF OLD
PC_2:
		MOV	[ECX]._COMM_NSYM_TYPE,AL
		MOV	COMM_TYPE,AL

		CALL	COMPARE_SIZES

		MOV	EAX,CV_TYPE
		JB	L9$

		MOV	DX,[ECX]._S_CV_TYPE3
		JA	L8$

		TEST	EAX,EAX
		JZ	L9$

		AND	EDX,0FFFFH
		JNZ	L9$

		MOV	[ECX]._S_CV_TYPE3,AX
		MOV	EDX,CURNMOD_GINDEX

		MOV	[ECX]._COMM_MOD_GINDEX,EDX
L9$:
		RET

L8$:
		JMP	MAKE_COMM_FINI

PREV_COMMUNAL	ENDP


COMM_ALIAS_DEFINED	PROC	NEAR
		;
		;IN ALIAS-DEFINED LIST, FORCE COMMUNAL
		;
		CALL	REMOVE_FROM_ALIAS_DEFINED_LIST
		JMP	CMC_1

COMM_ALIAS_DEFINED	ENDP


COMM__IMP__	PROC	NEAR
		;
		;IN LAZY LIST, FORCE COMMUNAL
		;
		CALL	REMOVE_FROM__IMP__LIST
		JMP	CMC_1

COMM__IMP__	ENDP


COMM_LAZY	PROC	NEAR
		;
		;IN LAZY LIST, FORCE COMMUNAL
		;
		CALL	REMOVE_FROM_LAZY_LIST
		JMP	CMC_1

COMM_LAZY	ENDP


COMM_LAZY_DEFINED	PROC	NEAR
		;
		;IN LAZY_DEFINED LIST, FORCE COMMUNAL
		;
		CALL	REMOVE_FROM_LAZY_DEFINED_LIST
		JMP	CMC_1

COMM_LAZY_DEFINED	ENDP


COMM_ALIASED	PROC	NEAR
		;
		;IN ALIASED LIST, FORCE COMMUNAL
		;
		CALL	REMOVE_FROM_ALIASED_LIST
		JMP	CMC_1

COMM_ALIASED	ENDP


WEAK_DEF_MAKE_COMMUNAL	PROC	NEAR
		;
		;IN WEAK_DEFINED LIST, FORCE REAL DEFINITION
		;
		CALL	REMOVE_FROM_WEAK_DEFINED_LIST
		JMP	CMC_1

WEAK_DEF_MAKE_COMMUNAL	ENDP


WEAK_MAKE_COMMUNAL	PROC	NEAR
		;
		;IN WEAK LIST, FORCE REAL DEFINITION
		;
		CALL	REMOVE_FROM_WEAK_LIST
		JMP	CMC_1

WEAK_MAKE_COMMUNAL	ENDP


LIB_REFERENCE	PROC	NEAR
		;
		;UNREFERENCED, IN A LIBRARY
		;IF THIS MODULE, MAKE COMMUNAL, ELSE, REFERENCE IT LIKE EXTERNAL
		;
		GETT	DL,COMDEF_SEARCH		;MAKE COMMUNAL IF COMDEFS DO NOT CAUSE LIB SEARCH
		MOV	EBX,CURN_LIB_MODULE

		TEST	DL,DL
		JZ	MAKE_COMMUNAL

		MOV	EDX,[ECX]._S_LIB_MODULE
		MOV	ESI,CURNLIB_GINDEX

		CMP	EDX,EBX
		JNZ	L5$

		CMP	[ECX]._S_LIB_GINDEX,ESI
		JZ	MAKE_COMMUNAL
L5$:
		RET

LIB_REFERENCE	ENDP


COUNT_MAKE_COMMUNAL	PROC	NEAR
		;
		;REFERENCED EXTERNAL
		;
		CALL	REMOVE_FROM_EXTERNAL_LIST
CMC_1::
MAKE_COMMUNAL::
		;
		;ECX IS PHYS, EAX IS GINDEX
		;
		;need to make this a communal
		;now add it to communal_list
		;
		MOV	BL,[ECX]._S_REF_FLAGS
		MOV	DL,COMM_TYPE

		AND	BL,MASK S_REFERENCED
		JZ	MC_1

		SUB	DL,NSYM_NCOMM_UNREF-NSYM_COMM_NEAR	;CHANGE TO REFERENCED TYPE

		MOV	COMM_TYPE,DL
		CALL	ADD_TO_COMMUNAL_LIST
MC_1:
;		MOV	AX,COMM_SIZE_A.HW
;		OR	AX,COMM_SIZE_B.HW
;		JNZ	MAKE_HUGE_COMMUNAL
MAKE_COMM_FINI::
		MOV	EAX,COMM_SIZE_A
		MOV	EBX,COMM_SIZE_B
		MOV	[ECX]._COMM_SIZE_A,EAX
		MOV	[ECX]._COMM_SIZE_B,EBX
MAKE_COMM_FINI_1:
		MOV	EAX,CURNMOD_GINDEX
		MOV	EBX,CV_TYPE

		MOV	[ECX]._S_CV_TYPE3,BX
		MOV	BL,COMM_TYPE

		MOV	[ECX]._COMM_MOD_GINDEX,EAX
		MOV	[ECX]._COMM_NSYM_TYPE,BL
COMM_IGNORE::
		RET

COUNT_MAKE_COMMUNAL	ENDP


NEXT_MIC_NUMBER	PROC	NEAR
		;
		;RETURN NUMBER IN EAX
		;
		MOV	AL,[ESI]		;ONE BYTE IS MOST LIKELY
		INC	ESI

		CMP	AL,80H
		JA	L1$

		AND	EAX,0FFH

		RET

L1$:
		CMP	AL,129		;2 BYTES NEXT LIKELY
		JNZ	L2$

		MOV	EAX,[ESI]
		ADD	ESI,2

		AND	EAX,0FFFFH

		RET

L2$:
		CMP	AL,132		;3 BYTES NEXT LIKELY
		JNZ	L3$

		MOV	EAX,[ESI]
		ADD	ESI,3

		AND	EAX,0FFFFFFH

		RET

L3$:
		CMP	AL,136		;4 BYTES LEAST LIKELY
		JNZ	FAIL

		MOV	EAX,[ESI]
		ADD	ESI,4

		RET

FAIL:
		MOV	AL,MIC_NUM_ERR
		push	EAX
		call	_err_abort
		RET

NEXT_MIC_NUMBER	ENDP


PROCESS_VIRDEF	PROC	NEAR
		;
		;EAX IS GINDEX, ECX IS SYMBOL PHYSICAL ADDRESS, COMM_NUMBER IS SEGMOD_LINDEX
		;
		;OK, WE NEED TO SET UP VARIABLES TO LOOK LIKE A COMDAT...
		;
		MOV	EBX,SYMBOL_LARRAY._LARRAY_LIMIT
		MOV	COMDAT_GINDEX,EAX

		ADD	EBX,4000H
		MOV	DL,10H

		MOV	MYCOMDAT_LINDEX,EBX		;MYCOMDAT_LINDEX IS 4000H + EXTERNAL LINDEX #
		XOR	EAX,EAX

		MOV	COMDAT_ATTRIB,DL		;PICK ANY, EXPLICIT SEGMOD
		MOV	COMDAT_GROUP_LINDEX,EAX		;=0

		MOV	EBX,SYM_HASH_MOD
		MOV	COMDAT_ALIGN,AL			;=0 = USE SEGMOD

		TEST	EBX,EBX
		JZ	L1$

		MOV	AL,MASK CD_LOCAL
		XOR	EBX,EBX
L1$:
		MOV	COMDAT_FLAGS,AL			;COMDAT_FLAGS HAS LOCAL BIT
		MOV	BL,COMM_NUMBER

		OR	AL,MASK MCD_ACTIVE
		MOV	COMDAT_SEGMOD_LINDEX,EBX

		MOV	MCD_FLAGS,AL			;MCD_FLAGS REFLECTS COMDEF VS LCOMDF
		MOV	EAX,MYCOMDAT_LINDEX

		CALL	MYCOMDAT_INSTALL		;DS:BX IS PHYSICAL
		ASSUME	ECX:PTR MYCOMDAT_STRUCT
		;
		;NEW INSTANCE, IF ALREADY THERE, FLUSH OLD ONE
		;
		MOV	DL,[ECX]._MCD_FLAGS
		MOV	EBX,[ECX]._MCD_SYMBOL_GINDEX

		AND	DL,MASK MCD_ACTIVE
		JZ	L23$

		TEST	EBX,EBX
		JZ	L23$

		CALL	FLUSH_COMDAT			;ANOTHER INSTANCE, FLUSH OLD ONE
L23$:
		;
		;DEFINE ITEMS IN MYCOMDAT
		;
		MOV	AX,WPTR COMDAT_ATTRIB		;_ALIGN
		MOV	EDX,COMDAT_SEGMOD_LINDEX

		MOV	WPTR [ECX]._MCD_ATTRIB,AX
		MOV	[ECX]._MCD_SEGMOD_LINDEX,EDX

		MOV	EBX,COMDAT_GROUP_LINDEX
		MOV	AL,COMDAT_FLAGS

		MOV	EDX,COMM_SIZE_A
		AND	AL,MASK CD_DATA_IN_CODE+MASK CD_LOCAL	;SAVE THESE FLAGS

		MOV	[ECX]._MCD_GROUP_LINDEX,EBX
		OR	AL,MASK MCD_ACTIVE

		MOV	[ECX]._MCD_SIZE,EDX
		MOV	[ECX]._MCD_FLAGS,AL

		MOV	MCD_FLAGS,AL
		MOV	EAX,COMDAT_GINDEX

		CONVERT	ECX,EAX,SYMBOL_GARRAY
		CALL	HANDLE_COMDAT

		RET

PROCESS_VIRDEF	ENDP


		.CONST

		ALIGN	4

COMDEF_TABLE	LABEL	DWORD

		DD	MAKE_COMMUNAL		;UNDEFINED
		DD	COMM_IGNORE		;ALREADY ASEG, FINISHED
		DD	PREV_RELOC		;ALREADY RELOCATABLE, CODE?
		DD	PREV_COMMUNAL		;NEAR COMMUNAL
		DD	PREV_COMMUNAL		;FAR_COMMUNAL
		DD	PREV_COMMUNAL_HUGE	;HUGE COMMUNAL
		DD	COMM_IGNORE		;ALREADY CONSTANT, FINISHED
		DD	LIB_REFERENCE		;IN A LIB, NOT REFERENCED, IF THIS MODULE, MAKE COMMUNAL, ELSE REFERENCE AS DATA...
		DD	PREV_DEF_1		;IMPORTED, CANNOT BE DEFINED
		DD	MAKE_COMMUNAL		;PROMISED
		DD	COUNT_MAKE_COMMUNAL	;REFERENCED EXTERNAL
		DD	WEAK_MAKE_COMMUNAL	;WEAK_EXTRN
		DD	MAKE_COMMUNAL		;POS_WEAK
		DD	ME_DONE_COMM		;LIBRARY-REFERENCED, MARK REFERENCE AS DATA
		DD	MAKE_COMMUNAL		;__imp__UNREF
		DD	COMM_ALIASED		;ALIASED, COMDEF OVERRIDES
		DD	PREV_COMDAT		;PREVIOUSLY COMDAT, WAS IT DATA ?
		DD	WEAK_DEF_MAKE_COMMUNAL	;WEAK-DEFINED, MAKE IT COMMUNAL
		DD	MAKE_COMMUNAL		;WEAK-UNREF, MAKE IT COMMUNAL
		DD	MAKE_COMMUNAL		;ALIASED-UNREF, MAKE IT COMMUNAL
		DD	MAKE_COMMUNAL		;POS-LAZY, MAKE IT COMMUNAL
		DD	COMM_LAZY		;LAZY, MAKE IT COMMUNAL
		DD	MAKE_COMMUNAL		;LAZY-UNREF, MAKE IT COMMUNAL
		DD	COMM_ALIAS_DEFINED	;ALIAS-DEFINED, MAKE IT COMMUNAL
		DD	COMM_LAZY_DEFINED	;LAZY-DEFINED, MAKE IT COMMUNAL
		DD	PREV_COMM_UNREF		;NCOMM-UNREF, TEST IT
		DD	PREV_COMM_UNREF		;FCOMM-UNREF, TEST IT
		DD	PREV_COMM_UNREF_HUGE	;HCOMM-UNREF,TEST IT
		DD	COMM__IMP__
		DD	MAKE_COMMUNAL		;UNDECORATED, CANNOT

.ERRNZ	($-COMDEF_TABLE)-NSYM_SIZE*2


		END

